﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//HashSet主要是设计用来做高性能集运算的，例如对两个集合求交集、并集、差集等。集合中包含一组不重复出现且无特性顺序的元素，HashSet拒绝接受重复的对象。

//HashSet的一些特性如下:
//a.HashSet中的值不能重复且没有顺序。
//　　b.HashSet的容量会按需自动添加
//　　
//　　HashSet代替List问题
//NET3.5多了个HasSet<T>用来存储集合。从名称可以看出，它是基于Hash的。可以简单理解为没有Value的Dictionary<TKey, TValue>。
//HashSet<T>不能用索引访问，不能存储重复数据，元素T必须正确实现了Equals和GetHashCode。
//那它的优势是什么呢？
//检索的性能。简单的说它的Contains方法的性能在大数据量时比List<T>好得多。HashSet<T>的Contains方法复杂度是O(1)，List<T>的Contains方法复杂度是O(n)。
//那么，在集合的目的是为了检索的情况下，我们应该使用HashSet<T>代替List<T>。比如一个存储关键字的集合，运行的时候通过其Contains方法检查输入字符串是否关键字。。
namespace LeetCode100Hot.c_常用泛型容器
{
    internal class HashSet
    {

        static void MainHashSet(string[] args)
        {
            HashSet<string> hashSet = new HashSet<string>();
            hashSet.Add("A");
            hashSet.Add("B");
            hashSet.Add("C");
            hashSet.Add("D");
            hashSet.Add("D");//重复的不会加入，也不会报错
            if (hashSet.Contains("D"))///查询操作
                Console.WriteLine("The required element is available.");
            else
                Console.WriteLine("The required element isn’t available.");
            Console.WriteLine("The number of elements is: {0}", hashSet.Count);

            string item = "D";
            if (hashSet.Contains(item))
            {
                hashSet.Remove(item);
            }
            foreach(string i in hashSet)
            {
                Console.WriteLine(i);
            }
            //HashSet 的 set操作
            //HashSet提供了非常多的方法用于 set集合 操作上，比如说：IntersectWith, UnionWith, IsProperSubsetOf, ExceptWith, 和 SymmetricExceptWith

            //这个 IsProperSubsetOf 用于判断 HashSet 是否为某一个集合的完全子集，可以看下面的例子：
            //包含关系
            HashSet<string> setA = new HashSet<string>() { "A", "B", "C", "D" };
            HashSet<string> setB = new HashSet<string>() { "A", "B", "C", "X" };
            HashSet<string> setC = new HashSet<string>() { "A", "B", "C", "D", "E" };
            if (setA.IsProperSubsetOf(setC))
                Console.WriteLine("setC contains all elements of setA.");
            if (!setA.IsProperSubsetOf(setB))
                Console.WriteLine("setB does not contains all elements of setA.");

            //UnionWith方法常用于集合的合并，比如说下面的代码：
            //并集
            Console.WriteLine("A和B的并集 ");
            setA.UnionWith(setB);
            foreach (string str in setA)
            {
                Console.WriteLine(str);
            }
            //交集
            //IntersectWith 方法常用于表示两个 HashSet 的交集
            Console.WriteLine("A和B的交集");
            setA.IntersectWith(setB);
            foreach (string str in setA)
            {
                Console.WriteLine(str);
            }
            //ExceptWith 方法表示数学上的减法操作，这个时间复杂度是 O(N)，假定你有两个HashSet 集合，分别叫 setA 和 setB，并且用了下面的语句。
            setA.ExceptWith(setB);
            Console.WriteLine("setB");
            foreach (string str in setB)
            {
                Console.WriteLine(str);
            }
            Console.WriteLine("A-B");
            // setA中有，setB中没有 的最终结果，如果还不明白的话,使用如下代码辅助理解：
            foreach (string str in setA)
            {
                Console.WriteLine(str);
            }


            //            SymmetricExceptWith
            //SymmetricExceptWith 方法常用于修改一个 HashSet 来存放两个 HashSet 都是唯一的元素，换句话说，我要的就是两个集合都不全有的元素，如果还不明白的话，考虑下面的代码段：

            HashSet<string> setE = new HashSet<string>() { "A", "B", "C", "D", "E" };
            HashSet<string> setF = new HashSet<string>() { "A", "X", "C", "Y" };
            setE.SymmetricExceptWith(setF);
            Console.WriteLine("E-SymmetricExceptWith-F");
            foreach (string str in setE)
            {
                Console.WriteLine(str);
            }


        }

    }
}
